﻿// ***********************************************************************
// Assembly         : Wicresoft.EKA.NRemedy
// Author           : William Wang(王吉彬)
// Created          : 02-19-2013
//
// Last Modified By : William Wang(王吉彬)
// Last Modified On : 04-04-2013
// ***********************************************************************
// <copyright file="ARProxy.cs" company="Wicresoft">
//     Copyright (c) Wicresoft. All rights reserved.
// </copyright>
// <summary></summary>
// ***********************************************************************

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using BMC.ARSystem;

namespace Wicresoft.EKA.NRemedy
{
    /// <summary>
    /// ARProxy
    /// </summary>
    /// <typeparam name="T">Type</typeparam>
    /// <example>
    ///   <code>
    /// GlobalSettings.SetCharacterEncoding("UTF8");    //GlobalSetting 里面
    /// string ARServer = ConfigurationManager.AppSettings["ARServer"];
    /// string ARUid = ConfigurationManager.AppSettings["ARUid"];
    /// string ARPwd = ConfigurationManager.AppSettings["ARPwd"];
    /// ARLoginContext context = new ARLoginContext(ARServer, ARUid, ARPwd);
    /// ARProxy&lt;Rack&gt;  rack = new ARProxy&lt;Rack&gt; (context);
    /// string querystr = string.Format("\'InstanceId\'=\"{0}\"", instanceId.Text);
    /// Rack ra = rack.GetEntryByQuery(querystr)[0];
    /// ra.Loaction="rack_Location"
    /// rack.SetEntry(ra);
    ///   </code>
    ///   </example>
    public class ARProxy<T> where T : ARBaseForm
    {
        /// <summary>
        /// The login context
        /// </summary>
        protected ARLoginContext loginContext;

        /// <summary>
        /// Constructor 1
        /// </summary>
        /// <param name="context">LoginContext</param>
        /// <exception cref="System.ArgumentNullException">context
        /// or
        /// context.Server
        /// or
        /// context.User
        /// or
        /// context.Password</exception>
        /// <!--William Wang-->
        public ARProxy(ARLoginContext context)
        {
            if (context == null) throw new ArgumentNullException("context");
            if (string.IsNullOrWhiteSpace(context.Server)) throw new ArgumentNullException("context.Server");
            if (string.IsNullOrWhiteSpace(context.User)) throw new ArgumentNullException("context.User");
            if (string.IsNullOrWhiteSpace(context.Password)) throw new ArgumentNullException("context.Password");
            loginContext = context;
        }

        /// <summary>
        /// Create AR Entry by model, and indicate modelbinder、FormNameUtil
        /// </summary>
        /// <param name="entry">model</param>
        /// <param name="binder">ModelBinder</param>
        /// <param name="getFormName">getFormName Delegate</param>
        /// <returns>System.String.</returns>
        /// <exception cref="System.ArgumentNullException">entry
        /// or
        /// binder
        /// or
        /// getFormName</exception>
        /// <!--William Wang-->
        public string CreateEntry(T entry, IModelBinder<T> binder, ARGetFormNameDelegate getFormName)
        {
            if (entry == null)
                throw new ArgumentNullException("entry");
            if (binder == null)
                throw new ArgumentNullException("binder");
            if (getFormName == null)
                throw new ArgumentNullException("getFormName");
            return loginContext.ServerInstance.CreateEntry(getFormName(typeof(T)), binder.UnBindForCreate(entry));
        }


        /// <summary>
        /// Create AR Entry by model using default modelbinder、GetFormName
        /// </summary>
        /// <param name="entry">model</param>
        /// <returns>System.String.</returns>
        /// <!--William Wang-->
        public string CreateEntry(T entry)
        {
            return CreateEntry(entry, DefaultFactory.CreateModelBinder<T>(), GetFormName);
        }

        /// <summary>
        /// Create list entry
        /// </summary>
        /// <param name="entries">List Model</param>
        /// <param name="binder">ModelBinder</param>
        /// <param name="getFormName">getFormName</param>
        /// <exception cref="System.ArgumentNullException">entries
        /// or
        /// binder
        /// or
        /// getFormName</exception>
        /// <!--William Wang-->
        public void CreateListEntry(IList<T> entries, IModelBinder<T> binder, ARGetFormNameDelegate getFormName)
        {
            if (entries == null || entries.Count == 0)
                throw new ArgumentNullException("entries");
            if (binder == null)
                throw new ArgumentNullException("binder");
            if (getFormName == null)
                throw new ArgumentNullException("getFormName");
            string formName = getFormName(typeof(T));
            foreach (T item in entries)
            {
                loginContext.ServerInstance.CreateEntry(formName, binder.UnBindForCreate(item));
            }
        }

        /// <summary>
        /// Create list entry
        /// </summary>
        /// <param name="entries">List Model</param>
        /// <exception cref="System.ArgumentNullException">entries</exception>
        /// <!--William Wang-->
        public void CreateListEntry(IList<T> entries)
        {
            if (entries == null || entries.Count == 0)
                throw new ArgumentNullException("entries");
            CreateListEntry(entries, DefaultFactory.CreateModelBinder<T>(), GetFormName);
        }

        /// <summary>
        /// Delete AR Entry by model, and indicate modelbinder、FormNameUtil
        /// </summary>
        /// <param name="entryID">model</param>
        /// <param name="getFormName">getFormName Delegate</param>
        /// <exception cref="System.ArgumentNullException">entry
        /// or
        /// getFormName</exception>
        /// <!--William Wang-->
        public void DeleteEntry(string entryID, ARGetFormNameDelegate getFormName)
        {
            if (string.IsNullOrWhiteSpace(entryID))
                throw new ArgumentNullException("entry");
            if (getFormName == null)
                throw new ArgumentNullException("getFormName");
            loginContext.ServerInstance.DeleteEntry(getFormName(typeof(T)), entryID, 0);
        }

        /// <summary>
        /// Delete AR Entry by model using default modelbinder、GetFormName
        /// </summary>
        /// <param name="entryID">model</param>
        /// <!--William Wang-->
        public void DeleteEntry(string entryID)
        {
            DeleteEntry(entryID, GetFormName);
        }

        /// <summary>
        /// Delete AR Entry by model, and indicate modelbinder、FormNameUtil
        /// </summary>
        /// <param name="entry">model</param>
        /// <param name="getFormName">getFormName Delegate</param>
        /// <exception cref="System.ArgumentNullException">entry
        /// or
        /// getFormName</exception>
        /// <!--William Wang-->
        public void DeleteEntry(T entry, ARGetFormNameDelegate getFormName)
        {
            if (entry == null)
                throw new ArgumentNullException("entry");
            if (getFormName == null)
                throw new ArgumentNullException("getFormName");
            loginContext.ServerInstance.DeleteEntry(getFormName(typeof(T)), GetEntryId(entry), 0);
        }

        /// <summary>
        /// Delete AR Entry by model using default modelbinder、GetFormName
        /// </summary>
        /// <param name="entry">model</param>
        /// <!--William Wang-->
        public void DeleteEntry(T entry)
        {
            DeleteEntry(entry, GetFormName);
        }

        /// <summary>
        /// Delete list entry
        /// </summary>
        /// <param name="entries">List Model</param>
        /// <param name="getFormName">getFormName</param>
        /// <exception cref="System.ArgumentNullException">entries
        /// or
        /// getFormName</exception>
        /// <!--William Wang-->
        public void DeleteListEntry(IList<T> entries, ARGetFormNameDelegate getFormName)
        {
            if (entries == null || entries.Count == 0)
                throw new ArgumentNullException("entries");
            if (getFormName == null)
                throw new ArgumentNullException("getFormName");
            string formName = getFormName(typeof(T));
            foreach (T item in entries)
            {
                loginContext.ServerInstance.DeleteEntry(formName, GetEntryId(item), 0);
            }
        }

        /// <summary>
        /// Delete list entry
        /// </summary>
        /// <param name="entries">List Model</param>
        /// <!--William Wang-->
        public void DeleteListEntry(IList<T> entries)
        {
            DeleteListEntry(entries, GetFormName);
        }

        /// <summary>
        /// Delete list entry
        /// </summary>
        /// <param name="entries">List Model</param>
        /// <param name="getFormName">getFormName</param>
        /// <exception cref="System.ArgumentNullException">entries
        /// or
        /// getFormName</exception>
        /// <!--William Wang-->
        public void DeleteListEntry(IList<string> entries, ARGetFormNameDelegate getFormName)
        {
            if (entries == null || entries.Count == 0)
                throw new ArgumentNullException("entries");
            if (getFormName == null)
                throw new ArgumentNullException("getFormName");
            string formName = getFormName(typeof(T));
            foreach (string item in entries)
            {
                loginContext.ServerInstance.DeleteEntry(formName, item, 0);
            }
        }

        /// <summary>
        /// Delete list entry
        /// </summary>
        /// <param name="entries">List Model</param>
        /// <!--William Wang-->
        public void DeleteListEntry(IList<string> entries)
        {
            DeleteListEntry(entries, GetFormName);
        }

        /// <summary>
        /// Delete entris by query
        /// </summary>
        /// <param name="qualification">for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"</param>
        /// <param name="getFormName">getFormName</param>
        /// <param name="useLocale">whether to use locale while getting the matched entry list</param>
        /// <exception cref="System.ArgumentNullException">qualification
        /// or
        /// getFormName</exception>
        /// <!--William Wang-->
        public void DeleteEntryByQuery(string qualification, ARGetFormNameDelegate getFormName,
          bool useLocale = false)
        {
            if (string.IsNullOrWhiteSpace(qualification))
                throw new ArgumentNullException("qualification");
            if (getFormName == null)
                throw new ArgumentNullException("getFormName");

            var entries = loginContext.ServerInstance.GetListEntryDescription(getFormName(typeof(T)), qualification);
            foreach (EntryDescription item in entries)
            {
                EntryDescription des = (EntryDescription)item;
                loginContext.ServerInstance.DeleteEntry(getFormName(typeof(T)), des.EntryId);
            }
        }


        /// <summary>
        /// Delete entris by query
        /// </summary>
        /// <param name="qualification">for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"</param>
        /// <param name="useLocale">whether to use locale while getting the matched entry list</param>
        /// <!--William Wang-->
        public void DeleteEntryByQuery(string qualification, bool useLocale = false)
        {
            DeleteEntryByQuery(qualification, GetFormName, useLocale);
        }

        /// <summary>
        /// Set AR Entry by model
        /// </summary>
        /// <param name="entry">model</param>
        /// <param name="binder">ModelBinder</param>
        /// <param name="getFormName">getFormName Delegate</param>
        /// <exception cref="System.ArgumentNullException">entry
        /// or
        /// binder
        /// or
        /// getFormName</exception>
        /// <!--William Wang-->
        public void SetEntry(T entry, IModelBinder<T> binder, ARGetFormNameDelegate getFormName)
        {
            if (entry == null)
                throw new ArgumentNullException("entry");
            if (binder == null)
                throw new ArgumentNullException("binder");
            if (getFormName == null)
                throw new ArgumentNullException("getFormName");
            loginContext.ServerInstance.SetEntry(getFormName(typeof(T)), GetEntryId(entry), binder.UnBindForUpdate(entry));
        }


        /// <summary>
        /// Set AR Entry by model using default modelbinder、default getFormName
        /// </summary>
        /// <param name="entry">model</param>
        /// <!--William Wang-->
        public void SetEntry(T entry)
        {
            SetEntry(entry, DefaultFactory.CreateModelBinder<T>(), GetFormName);
        }

        /// <summary>
        /// Set list entry
        /// </summary>
        /// <param name="entries">List Model</param>
        /// <param name="binder">ModelBinder</param>
        /// <param name="getFormName">getFormName</param>
        /// <exception cref="System.ArgumentNullException">entries
        /// or
        /// binder
        /// or
        /// getFormName</exception>
        /// <!--William Wang-->
        public void SetListEntry(IList<T> entries, IModelBinder<T> binder, ARGetFormNameDelegate getFormName)
        {
            if (entries == null || entries.Count == 0)
                throw new ArgumentNullException("entries");
            if (binder == null)
                throw new ArgumentNullException("binder");
            if (getFormName == null)
                throw new ArgumentNullException("getFormName");
            string formName = getFormName(typeof(T));
            foreach (T item in entries)
            {
                loginContext.ServerInstance.SetEntry(formName,
                    GetEntryId(item), binder.UnBindForUpdate(item));
            }
        }

        /// <summary>
        /// Set list entry
        /// </summary>
        /// <param name="entries">List Model</param>
        /// <!--William Wang-->
        public void SetListEntry(IList<T> entries)
        {
            SetListEntry(entries, DefaultFactory.CreateModelBinder<T>(), GetFormName);
        }

        /// <summary>
        /// Set entris by query
        /// </summary>
        /// <param name="entry">entry</param>
        /// <param name="qualification">for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"</param>
        /// <param name="binder">binder</param>
        /// <param name="getFormName">ARGetFormNameDelegate</param>
        /// <param name="noMatchOption">NoMatchOption</param>
        /// <param name="multiMatchOption">MultiMatchOption</param>
        /// <param name="useLocale">whether to use locale while getting the matched entry list</param>
        /// <exception cref="System.ArgumentNullException">entry
        /// or
        /// qualification
        /// or
        /// binder
        /// or
        /// getFormName</exception>
        /// <!--William Wang-->
        public void SetEntryByQuery(T entry, string qualification, IModelBinder<T> binder, ARGetFormNameDelegate getFormName,
            Server.SetEntryByQuery_NoMatchOption noMatchOption = Server.SetEntryByQuery_NoMatchOption.NoAction,
            Server.SetEntryByQuery_MultiMatchOption multiMatchOption = Server.SetEntryByQuery_MultiMatchOption.ModifyAll, bool useLocale = false)
        {
            if (entry == null)
                throw new ArgumentNullException("entry");
            if (string.IsNullOrWhiteSpace(qualification))
                throw new ArgumentNullException("qualification");
            if (binder == null)
                throw new ArgumentNullException("binder");
            if (getFormName == null)
                throw new ArgumentNullException("getFormName");
            loginContext.ServerInstance.SetEntryByQuery(getFormName(typeof(T)), qualification,
                noMatchOption, multiMatchOption, binder.UnBindForUpdate(entry), useLocale);
        }

        /// <summary>
        /// Set entris by query
        /// </summary>
        /// <param name="entry">entry</param>
        /// <param name="qualification">for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"</param>
        /// <param name="noMatchOption">NoMatchOption</param>
        /// <param name="multiMatchOption">MultiMatchOption</param>
        /// <param name="useLocale">whether to use locale while getting the matched entry list</param>
        /// <!--William Wang-->
        public void SetEntryByQuery(T entry, string qualification, Server.SetEntryByQuery_NoMatchOption noMatchOption = Server.SetEntryByQuery_NoMatchOption.NoAction,
            Server.SetEntryByQuery_MultiMatchOption multiMatchOption = Server.SetEntryByQuery_MultiMatchOption.ModifyAll, bool useLocale = false)
        {
            SetEntryByQuery(entry, qualification, DefaultFactory.CreateModelBinder<T>(), GetFormName, noMatchOption, multiMatchOption, useLocale);
        }

        /// <summary>
        /// Get AR Entry by model, and indicate modelbinder、GetFormName
        /// </summary>
        /// <param name="entryID">entryID</param>
        /// <param name="binder">ModelBinder</param>
        /// <param name="getFormName">getFormName Delegate</param>
        /// <returns>`0.</returns>
        /// <exception cref="System.ArgumentNullException">entry
        /// or
        /// binder
        /// or
        /// getFormName</exception>
        /// <!--William Wang-->
        public T GetEntry(string entryID, IModelBinder<T> binder, ARGetFormNameDelegate getFormName)
        {
            if (string.IsNullOrWhiteSpace(entryID))
                throw new ArgumentNullException("entry");
            if (binder == null)
                throw new ArgumentNullException("binder");
            if (getFormName == null)
                throw new ArgumentNullException("getFormName");
            return binder.Bind(loginContext.ServerInstance.GetEntry(getFormName(typeof(T)), entryID, null));
        }

        /// <summary>
        /// Get AR Entry by model using default modelbinder、default GetFormName
        /// </summary>
        /// <param name="entryID">entryID</param>
        /// <returns>`0.</returns>
        /// <!--William Wang-->
        public T GetEntry(string entryID)
        {
            return GetEntry(entryID, DefaultFactory.CreateModelBinder<T>(), GetFormName);
        }

        /// <summary>
        /// Get AR Entry by model, and indicate modelbinder、GetFormName
        /// </summary>
        /// <param name="entryID">entryID</param>
        /// <param name="columns">The columns.</param>
        /// <param name="binder">ModelBinder</param>
        /// <param name="getFormName">getFormName Delegate</param>
        /// <returns>`0.</returns>
        /// <exception cref="System.ArgumentNullException">entry
        /// or
        /// binder
        /// or
        /// getFormName</exception>
        /// <!--William Wang-->
        public T GetEntryWithFields(string entryID, List<uint> columns, IModelBinder<T> binder, ARGetFormNameDelegate getFormName)
        {
            if (string.IsNullOrWhiteSpace(entryID))
                throw new ArgumentNullException("entry");
            if (binder == null)
                throw new ArgumentNullException("binder");
            if (getFormName == null)
                throw new ArgumentNullException("getFormName");
            return binder.BindWithIDS(loginContext.ServerInstance.GetEntry(getFormName(typeof(T)), entryID, GetFieldIdListFromIDs(columns)));
        }

        /// <summary>
        /// Get AR Entry by model using default modelbinder、default GetFormName
        /// </summary>
        /// <param name="entryID">entryID</param>
        /// <param name="columns">The columns.</param>
        /// <returns>`0.</returns>
        /// <!--William Wang-->
        public T GetEntryWithFields(string entryID, List<uint> columns)
        {
            return GetEntryWithFields(entryID, columns, DefaultFactory.CreateModelBinder<T>(), GetFormName);
        }

        /// <summary>
        /// Get entris by query
        /// </summary>
        /// <param name="qualification">for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"</param>
        /// <param name="columns">The columns.</param>
        /// <param name="binder">ModelBinder</param>
        /// <param name="getFormName">getFormName Delegate</param>
        /// <returns>IList{`0}.</returns>
        /// <exception cref="System.ArgumentNullException">qualification
        /// or
        /// binder
        /// or
        /// getFormName</exception>
        /// <exception cref="System.Exception">Please input one column id</exception>
        /// <!--William Wang-->
        public IList<T> GetListEntry(string qualification, List<uint> columns, IModelBinder<T> binder, ARGetFormNameDelegate getFormName)
        {
            //TODO : if String.IsNullOrEmpty(qualification), all list will be returned?
            if (string.IsNullOrWhiteSpace(qualification))
                throw new ArgumentNullException("qualification");
            if (binder == null)
                throw new ArgumentNullException("binder");
            if (getFormName == null)
                throw new ArgumentNullException("getFormName");
            if (null == columns || columns.Count == 0) throw new Exception("Please input one column id");
            if (!columns.Contains(1u))
            {
                columns.Add(1u);
            }
            EntryFieldValueList entrys = loginContext.ServerInstance.GetListEntry(getFormName(typeof(T)),
                qualification, GetEntryListFieldListFromIDs(columns));
            return binder.BindList(entrys);
        }

        /// <summary>
        /// Get entris by query
        /// </summary>
        /// <param name="qualification">for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"</param>
        /// <param name="columns">The columns.</param>
        /// <returns>IList{`0}.</returns>
        /// <!--William Wang-->
        public IList<T> GetListEntry(string qualification, List<uint> columns = null)
        {
            return GetListEntry(qualification, columns, DefaultFactory.CreateModelBinder<T>(), GetFormName);
        }

        /// <summary>
        /// Get Paged Entries
        /// </summary>
        /// <param name="qualification">for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"</param>
        /// <param name="columns">The columns.</param>
        /// <param name="binder">ModelBinder</param>
        /// <param name="getFormName">getFormName Delegate</param>
        /// <param name="pageIndex">Index Start</param>
        /// <param name="pageSize">Page Size</param>
        /// <param name="numMatches">Return Number</param>
        /// <param name="sortInfoList">Order by</param>
        /// <returns>IList{`0}.</returns>
        /// <exception cref="System.ArgumentNullException">binder
        /// or
        /// getFormName</exception>
        /// <exception cref="System.Exception">Please input one column id</exception>
        public IList<T> GetPagedEntry(string qualification, List<uint> columns, IModelBinder<T> binder, ARGetFormNameDelegate getFormName,
            uint pageIndex, uint pageSize, out int numMatches, ArrayList sortInfoList)
        {
            if (binder == null)
                throw new ArgumentNullException("binder");
            if (getFormName == null)
                throw new ArgumentNullException("getFormName");

            if (null == columns || columns.Count == 0) throw new Exception("Please input one column id");
            if (!columns.Contains(1u))
            {
                columns.Add(1u);
            }
            EntryFieldValueList entrys = loginContext.ServerInstance.GetPagedEntry(getFormName(typeof(T)), qualification, GetEntryListFieldListFromIDs(columns),
                pageIndex * pageSize, pageSize, out numMatches, sortInfoList);
            return binder.BindList(entrys);
        }



        /// <summary>
        /// Get Paged Entries
        /// </summary>
        /// <param name="qualification">for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"</param>
        /// <param name="columns">The columns.</param>
        /// <param name="pageIndex">Index Start</param>
        /// <param name="pageSize">Page Size</param>
        /// <param name="numMatches">Return Number</param>
        /// <param name="sortInfoList">Order by</param>
        /// <returns>IList{`0}.</returns>
        /// <!--William Wang-->
        public IList<T> GetPagedEntry(string qualification, List<uint> columns,
            uint pageIndex, uint pageSize, out int numMatches, ArrayList sortInfoList)
        {
            return GetPagedEntry(qualification, columns, DefaultFactory.CreateModelBinder<T>(), GetFormName, pageIndex, pageSize, out numMatches, sortInfoList);
        }

        /// <summary>
        /// Get Paged Entries
        /// </summary>
        /// <param name="qualification">for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"</param>
        /// <param name="columns">The columns.</param>
        /// <param name="binder">ModelBinder</param>
        /// <param name="getFormName">getFormName Delegate</param>
        /// <param name="pageIndex">Index Start</param>
        /// <param name="pageSize">Page Size</param>
        /// <param name="numMatches">Return Number</param>
        /// <param name="sortInfoList">Order by</param>
        /// <returns>IList{`0}.</returns>
        /// <exception cref="System.ArgumentNullException">binder
        /// or
        /// getFormName</exception>
        /// <exception cref="System.Exception">Please input one column id</exception>
        public IList<T> GetPagedEntry(string qualification, List<uint> columns, IModelBinder<T> binder, ARGetFormNameDelegate getFormName,
            uint pageIndex, uint pageSize, out int numMatches, int orderBy, string direction)
        {
            return GetPagedEntry(qualification, columns, binder, getFormName, pageIndex, pageSize, out numMatches, new ArrayList(){
                IdentifyOrderbyDirectionsGenerateSortInfo(orderBy, direction)}
            );
        }



        /// <summary>
        /// Get Paged Entries
        /// </summary>
        /// <param name="qualification">for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"</param>
        /// <param name="columns">The columns.</param>
        /// <param name="pageIndex">Index Start</param>
        /// <param name="pageSize">Page Size</param>
        /// <param name="numMatches">Return Number</param>
        /// <param name="sortInfoList">Order by</param>
        /// <returns>IList{`0}.</returns>
        /// <!--William Wang-->
        public IList<T> GetPagedEntry(string qualification, List<uint> columns,
            uint pageIndex, uint pageSize, out int numMatches, int orderBy, string direction)
        {
            return GetPagedEntry(qualification, columns, DefaultFactory.CreateModelBinder<T>(), GetFormName, pageIndex, pageSize, out numMatches, orderBy, direction);
        }


        /// <summary>
        /// Get Paged Entries
        /// </summary>
        /// <param name="qualification">for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"</param>
        /// <param name="columns">The columns.</param>
        /// <param name="binder">ModelBinder</param>
        /// <param name="getFormName">getFormName Delegate</param>
        /// <param name="startindex">Index Start</param>
        /// <param name="pageSize">Page Size</param>
        /// <param name="numMatches">Return Number</param>
        /// <param name="sortInfoList">Order by</param>
        /// <returns>IList{`0}.</returns>
        /// <exception cref="System.ArgumentNullException">binder
        /// or
        /// getFormName</exception>
        /// <exception cref="System.Exception">Please input one column id</exception>
        public IList<T> GetEntryWithStartIndexAndPagesize(string qualification, List<uint> columns, IModelBinder<T> binder, ARGetFormNameDelegate getFormName,
            uint startindex, uint pageSize, out int numMatches, ArrayList sortInfoList)
        {
            if (binder == null)
                throw new ArgumentNullException("binder");
            if (getFormName == null)
                throw new ArgumentNullException("getFormName");

            if (null == columns || columns.Count == 0) throw new Exception("Please input one column id");
            if (!columns.Contains(1u))
            {
                columns.Add(1u);
            }
            EntryFieldValueList entrys = loginContext.ServerInstance.GetPagedEntry(getFormName(typeof(T)), qualification, GetEntryListFieldListFromIDs(columns),
                startindex, pageSize, out numMatches, sortInfoList);
            return binder.BindList(entrys);
        }



        /// <summary>
        /// Get Paged Entries
        /// </summary>
        /// <param name="qualification">for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"</param>
        /// <param name="columns">The columns.</param>
        /// <param name="startindex">Index Start</param>
        /// <param name="pageSize">Page Size</param>
        /// <param name="numMatches">Return Number</param>
        /// <param name="sortInfoList">Order by</param>
        /// <returns>IList{`0}.</returns>
        /// <!--William Wang-->
        public IList<T> GetEntryWithStartIndexAndPagesize(string qualification, List<uint> columns,
            uint startindex, uint pageSize, out int numMatches, ArrayList sortInfoList)
        {
            return GetEntryWithStartIndexAndPagesize(qualification, columns, DefaultFactory.CreateModelBinder<T>(), GetFormName, startindex, pageSize, out numMatches, sortInfoList);
        }

        /// <summary>
        /// Get Paged Entries
        /// </summary>
        /// <param name="qualification">for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"</param>
        /// <param name="columns">The columns.</param>
        /// <param name="binder">ModelBinder</param>
        /// <param name="getFormName">getFormName Delegate</param>
        /// <param name="startindex">Index Start</param>
        /// <param name="pageSize">Page Size</param>
        /// <param name="numMatches">Return Number</param>
        /// <param name="sortInfoList">Order by</param>
        /// <returns>IList{`0}.</returns>
        /// <exception cref="System.ArgumentNullException">binder
        /// or
        /// getFormName</exception>
        /// <exception cref="System.Exception">Please input one column id</exception>
        public IList<T> GetEntryWithStartIndexAndPagesize(string qualification, List<uint> columns, IModelBinder<T> binder, ARGetFormNameDelegate getFormName,
            uint startindex, uint pageSize, out int numMatches, int orderBy, string direction)
        {

            return GetEntryWithStartIndexAndPagesize(qualification, columns, startindex, pageSize, out numMatches,
                new ArrayList() { IdentifyOrderbyDirectionsGenerateSortInfo(orderBy, direction) });
        }

        private SortInfo IdentifyOrderbyDirectionsGenerateSortInfo(int orderby, string direction)
        {
            var sort = new SortInfo(); ;
            sort.FieldId = orderby;
            if (direction.StartsWith("asc", StringComparison.InvariantCultureIgnoreCase))
            {
                sort.Order = SortInfo.SortOrder.Ascending;
            }
            else
            {
                sort.Order = SortInfo.SortOrder.Descending;
            }
            return sort;
        }

        /// <summary>
        /// Get Paged Entries
        /// </summary>
        /// <param name="qualification">for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"</param>
        /// <param name="columns">The columns.</param>
        /// <param name="startindex">Index Start</param>
        /// <param name="pageSize">Page Size</param>
        /// <param name="numMatches">Return Number</param>
        /// <param name="sortInfoList">Order by</param>
        /// <returns>IList{`0}.</returns>
        /// <!--William Wang-->
        public IList<T> GetEntryWithStartIndexAndPagesize(string qualification, List<uint> columns,
            uint startindex, uint pageSize, out int numMatches, int orderBy, string direction)
        {
            return GetEntryWithStartIndexAndPagesize(qualification, columns, DefaultFactory.CreateModelBinder<T>(), GetFormName, startindex, pageSize, out numMatches, orderBy, direction);
        }

        /// <summary>
        /// Gets the entry statistics.
        /// </summary>
        /// <param name="qualification">The qualification.</param>
        /// <param name="expression">The expression.</param>
        /// <param name="statCode">The stat code.</param>
        /// <param name="groupBy">The group by.</param>
        /// <param name="binder">The binder.</param>
        /// <param name="getFormName">Name of the get form.</param>
        /// <param name="vuiName">Name of the vui.</param>
        /// <returns>ArrayList.</returns>
        /// <exception cref="System.ArgumentNullException">binder
        /// or
        /// getFormName</exception>
        public ArrayList GetEntryStatistics(string qualification, string expression, uint statCode,
            int[] groupBy, IModelBinder<T> binder, ARGetFormNameDelegate getFormName,
            string vuiName = null)
        {
            if (binder == null)
                throw new ArgumentNullException("binder");
            if (getFormName == null)
                throw new ArgumentNullException("getFormName");
            return loginContext.ServerInstance.GetEntryStatistics(getFormName(typeof(T)), qualification, expression, statCode, groupBy);
        }

        /// <summary>
        /// Gets the entry statistics.
        /// </summary>
        /// <param name="qualification">The qualification.</param>
        /// <param name="expression">Expression to compute result for statistics other than COUNT</param>
        /// <param name="statCode">1 = Count, 2 = Sum, 3 = Average, 4 = Minimum, 5 = Maximum</param>
        /// <param name="groupBy">Field IDs to group by</param>
        /// <param name="vuiName">Name of the vui.</param>
        /// <returns>ArrayList.</returns>
        public ArrayList GetEntryStatistics(string qualification, string expression, uint statCode,
            int[] groupBy, string vuiName = null)
        {
            return GetEntryStatistics(qualification, expression, statCode, groupBy, DefaultFactory.CreateModelBinder<T>(), GetFormName, vuiName);
        }

        /// <summary>
        /// Gets the entry count by query.
        /// </summary>
        /// <param name="qualification">The qualification.</param>
        /// <param name="getFormName">Name of the get form.</param>
        /// <returns>System.Int32.</returns>
        public int GetEntryCountByQuery(string qualification, ARGetFormNameDelegate getFormName)
        {
            int count = 0;
            ArrayList entryIDs;
            if (string.IsNullOrWhiteSpace(qualification))
                entryIDs = loginContext.ServerInstance.GetListEntryDescription(GetFormName(typeof(T)), null);
            else
                entryIDs = loginContext.ServerInstance.GetListEntryDescription(GetFormName(typeof(T)), qualification);
            count = entryIDs.Count;
            return count;
        }

        /// <summary>
        /// Gets the entry count by query.
        /// </summary>
        /// <param name="qualification">The qualification.</param>
        /// <returns>System.Int32.</returns>
        public int GetEntryCountByQuery(string qualification)
        {
            return GetEntryCountByQuery(qualification, GetFormName);
        }
        /// <summary>
        /// get the formname
        /// </summary>
        /// <param name="t">The t.</param>
        /// <returns>form name</returns>
        /// <!--William Wang-->
        protected string GetFormName(Type t)
        {
            string name = string.Empty;
            var formAttribute = t.GetCustomAttributes(false).Where(a => a is ARFormAttribute).FirstOrDefault() as ARFormAttribute;
            if (formAttribute != null)
            {
                name = formAttribute.FormName;
            }
            return name;
        }

        /// <summary>
        /// get the entry ID
        /// </summary>
        /// <param name="entity">model object</param>
        /// <returns>System.String.</returns>
        /// <exception cref="System.ArgumentNullException">entity</exception>
        /// <!--William Wang-->
        private string GetEntryId(T entity)
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }
            foreach (PropertyInfo item in typeof(T).GetProperties())
            {
                if (item.GetCustomAttributes(false).Where(a => a is AREntryKeyAttribute).Count() != 0)
                {
                    return item.GetValue(entity, null).ToString();
                }
            }
            return string.Empty;
        }


        /// <summary>
        /// Gets the entry list field list from I ds.
        /// </summary>
        /// <param name="ids">The ids.</param>
        /// <returns>EntryListFieldList.</returns>
        private static EntryListFieldList GetEntryListFieldListFromIDs(IList<uint> ids)
        {
            EntryListFieldList fieldIDList = new EntryListFieldList();
            if (ids == null || ids.Count == 0)
            {
                fieldIDList = null;
            }
            else
            {
                foreach (var id in ids)
                {
                    fieldIDList.Add(new EntryListField(id));
                }
            }
            return fieldIDList;
        }

        /// <summary>
        /// Gets the field id list from I ds.
        /// </summary>
        /// <param name="ids">The ids.</param>
        /// <returns>FieldIdList.</returns>
        private static FieldIdList GetFieldIdListFromIDs(IList<uint> ids)
        {
            FieldIdList fieldIDList = new FieldIdList();
            if (ids == null || ids.Count == 0)
            {
                fieldIDList = null;
            }
            else
            {
                foreach (var id in ids)
                {
                    fieldIDList.Add(id);
                }
            }
            return fieldIDList;
        }
    }

}
